using System;
using System.Drawing;
using System.Xml;

namespace PhotoFramePublishingPlugin
{
    internal static class SessionHelper
    {
        private const int DefaultMaxWidth = 0;
        private const int DefaultMaxHeight = 0;

        private const bool DefaultShouldAddBorders = false;
        private const bool DefaultShouldShortenFileNames = false;

        private const string PublishParametersXPath = "/PhotoGalleryPublishSession/PublishParameters";
        private const string MaxWidthElementName = "MaxWidth";
        private const string MaxHeightElementName = "MaxHeight";
        private const string DestinationRootElementName = "DestinationRoot";
        private const string ShouldAddBordersElementName = "ShouldAddBorders";
        private const string ShouldShortenFileNamesElementName = "ShouldShortenFileNames";

        public static void WriteMaxSize(XmlDocument sessionXml, int maxWidth, int maxHeight)
        {
            var publishParametersNode = sessionXml.SelectSingleNode(PublishParametersXPath);

            var maxWidthNode = publishParametersNode.SelectSingleNode(MaxWidthElementName);
            maxWidthNode.InnerText = Convert.ToString(maxWidth);

            var maxHeightNode = publishParametersNode.SelectSingleNode(MaxHeightElementName);
            maxHeightNode.InnerText = Convert.ToString(maxHeight);
        }

        public static Size ReadMaxSize(XmlDocument sessionXml)
        {
            var parametersNode = sessionXml.SelectSingleNode(PublishParametersXPath);
            if (parametersNode != null)
            {
                var maxWidthNode = parametersNode.SelectSingleNode(MaxWidthElementName);
                var maxHeightNode = parametersNode.SelectSingleNode(MaxHeightElementName);

                if (maxWidthNode != null && maxHeightNode != null)
                {
                    int maxWidth;
                    int maxHeight;

                    if (int.TryParse(maxWidthNode.InnerText, out maxWidth) &&
                        int.TryParse(maxHeightNode.InnerText, out maxHeight))
                    {
                        return new Size(maxWidth, maxHeight);
                    }
                }
            }

            return new Size(DefaultMaxWidth, DefaultMaxHeight);
        }

        public static void ClearMaxSize(XmlDocument sessionXml)
        {
            var publishParametersNode = sessionXml.SelectSingleNode(PublishParametersXPath);

            var maxWidthNode = publishParametersNode.SelectSingleNode(MaxWidthElementName);
            publishParametersNode.RemoveChild(maxWidthNode);

            var maxHeightNode = publishParametersNode.SelectSingleNode(MaxHeightElementName);
            publishParametersNode.RemoveChild(maxHeightNode);
        }

        public static void WriteDestination(XmlDocument sessionXml, string destinationRoot)
        {
            WriteString(sessionXml, DestinationRootElementName, destinationRoot);
        }

        public static void WriteShouldAddBorders(XmlDocument sessionXml, bool shouldAddBorders)
        {
            WriteBoolean(sessionXml, ShouldAddBordersElementName, shouldAddBorders);
        }

        public static ItemDetails ReadItemDetails(XmlDocument sessionXml, string mediaObjectId)
        {
            var itemXPath = string.Format("/PhotoGalleryPublishSession/ItemSet/Item[@id=\'{0}\']", mediaObjectId);
            var itemNode = sessionXml.SelectSingleNode(itemXPath);
            if (itemNode == null)
                return null;

            var originalFileNameNode = itemNode.SelectSingleNode("OriginalFileName");
            var originalFileName = originalFileNameNode.InnerText;

            var perceivedTypeNode = itemNode.SelectSingleNode("PerceivedType");
            var perceivedType = perceivedTypeNode.InnerText;

            return new ItemDetails(perceivedType, originalFileName);
        }

        public static string ReadDestination(XmlDocument sessionXml)
        {
            return ReadString(sessionXml, DestinationRootElementName);
        }

        public static bool ReadShouldAddBorders(XmlDocument sessionXml)
        {
            return ReadBoolean(sessionXml, ShouldAddBordersElementName, DefaultShouldAddBorders);
        }

        public static void WriteShouldShortenFileNames(XmlDocument sessionXml, bool shouldShortenFileNames)
        {
            WriteBoolean(sessionXml, ShouldShortenFileNamesElementName, shouldShortenFileNames);
        }

        public static bool ReadShouldShortenFileNames(XmlDocument sessionXml)
        {
            return ReadBoolean(sessionXml, ShouldShortenFileNamesElementName, DefaultShouldShortenFileNames);
        }

        private static bool ReadBoolean(XmlDocument sessionXml, string elementName, bool defaultValue)
        {
            var parametersNode = sessionXml.SelectSingleNode(PublishParametersXPath);
            if (parametersNode != null)
            {
                var elementNode = parametersNode.SelectSingleNode(elementName);
                if (elementNode != null)
                {
                    bool result;
                    if (bool.TryParse(elementNode.InnerText, out result))
                        return result;
                }
            }

            return defaultValue;
        }

        private static void WriteBoolean(XmlDocument sessionXml, string elementName, bool value)
        {
            var publishParametersNode = sessionXml.SelectSingleNode(PublishParametersXPath);

            var elementNode = publishParametersNode.SelectSingleNode(elementName);
            if (elementNode == null)
            {
                elementNode = sessionXml.CreateElement(elementName);
                publishParametersNode.AppendChild(elementNode);
            }

            elementNode.InnerText = Convert.ToString(value);
        }
       
        private static void WriteString(XmlDocument sessionXml, string elementName, string destinationRoot)
        {
            var publishParametersNode = sessionXml.SelectSingleNode(PublishParametersXPath);

            var elementNode = publishParametersNode.SelectSingleNode(elementName);
            if (elementNode == null)
            {
                elementNode = sessionXml.CreateElement(elementName);
                publishParametersNode.AppendChild(elementNode);
            }

            elementNode.InnerText = destinationRoot;
        }

        private static string ReadString(XmlDocument sessionXml, string elementName)
        {
            var publishParametersNode = sessionXml.SelectSingleNode(PublishParametersXPath);

            var elementNode = publishParametersNode.SelectSingleNode(elementName);
            if (elementNode == null)
                return null;

            return elementNode.InnerText;
        }
    }
}